﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.IO;

namespace BawangMemo.BackendModels
{
    public class WordRepository
    {
        public static List<WordWrapper> LoadWordsFromCourse(CourseWrapper course)
        {
            var result = new List<WordWrapper>();
            using (FileStream fs = new FileStream(course.WordsInfoPath, FileMode.Open))
            using (BinaryReader br = new BinaryReader(fs))
            {
                byte[] data = null;
                while ((data = br.ReadBytes(Constants.WORD_INFO_SIZE)) != null && data.Length > 0)
                {
                    WordInfo wi = DataAccess.BytesToObject(data) as WordInfo;
                    result.Add(new WordWrapper(course, wi));
                }
            }
            return result;
        }

        public static WordCard LoadWordCardFromCourse(CourseWrapper course, int wordId)
        {
            List<WordCard> list = (from elem in XDocument.Load(course.WordListPath).Descendants(
                             Constants.WORD_LIST_SUB_ELEMENT)
                                   where (elem.Attribute("id") != null &&
                                   wordId.ToString().Equals(elem.Attribute("id").Value))
                                   select WordCard.CreateInstance(
                                   Helper.GetAttributeValue(elem, "spell"),
                                   Helper.GetAttributeValue(elem, "meaning"),
                                   Helper.GetAttributeValue(elem, "synonym"),
                                   Helper.GetAttributeValue(elem, "antonym"),
                                   Helper.GetAttributeValue(elem, "mnemonics"),
                                   Helper.GetAttributeValue(elem, "leifan"),
                                   Helper.GetAttributeValue(elem, "derivation"),
                                   Helper.GetAttributeValue(elem, "place"),
                                   Helper.GetAttributeValue(elem, "webster"))).ToList();
            return list.Count > 0 ? list[0] : null;
        }

        internal static List<WordCard> LoadWordCardsFromCourse(CourseWrapper courseWrapper)
        {
            return (from elem in XDocument.Load(courseWrapper.WordListPath).Descendants(
                             Constants.WORD_LIST_SUB_ELEMENT)
                    select WordCard.CreateInstance(
                    Helper.GetAttributeValue(elem, "spell"),
                    Helper.GetAttributeValue(elem, "meaning"),
                    Helper.GetAttributeValue(elem, "synonym"),
                    Helper.GetAttributeValue(elem, "antonym"),
                    Helper.GetAttributeValue(elem, "mnemonics"),
                    Helper.GetAttributeValue(elem, "leifan"),
                    Helper.GetAttributeValue(elem, "derivation"),
                    Helper.GetAttributeValue(elem, "place"),
                    Helper.GetAttributeValue(elem, "webster"))).ToList();
        }


        internal static void SaveWordInfo(string path, WordInfo wordInfo)
        {
            using (FileStream fs = new FileStream(path, FileMode.Open))
            using (BinaryWriter bw = new BinaryWriter(fs))
            {
                fs.Seek(Constants.WORD_INFO_SIZE * (wordInfo.WordId - 1), SeekOrigin.Begin);
                bw.Write(DataAccess.ObjectToBytes(wordInfo, Constants.WORD_INFO_SIZE));
                bw.Flush();
                bw.Close();
            }
        }

        internal static List<XElement> LoadWordElementsFromBook(string bookPath)
        {
            return (from elem in XDocument.Load(bookPath).Element(Constants.WORD_LIST_ROOT_ELEMENT).
                        Elements("word") select elem).ToList();
        }

        internal static void SaveAllWordInfo(List<WordInfo> infos, string path)
        {
            using (FileStream fs = new FileStream(path, FileMode.Create))
            using (BinaryWriter bw = new BinaryWriter(fs))
            {
                for (int i = 0; i < infos.Count; i++)
                {
                    WordInfo wi = infos[i];
                    bw.Write(DataAccess.ObjectToBytes(wi, Constants.WORD_INFO_SIZE));
                }
                bw.Flush();
                bw.Close();
            }
        }

        //internal static XElement LoadWordElementFromCourse(string coursePath, int id)
        //{
        //    var temp = (from elem in XDocument.Load(coursePath).Element(Constants.WORD_LIST_ROOT_ELEMENT).
        //                Elements(Constants.WORD_LIST_SUB_ELEMENT)
        //                where (elem.Attribute("id") != null && elem.Attribute("id").Value.Equals(id.ToString()))
        //                select elem).ToList();
        //    if (temp.Count != 1)
        //    {
        //        throw new ApplicationException(String.Format("There are {0} elements with ID={1} in {2}.",
        //            temp.Count, id, coursePath));
        //    }
        //    return temp[0];
        //}

        internal static XElement WordCardToWordElement(WordCard wordCard)
        {
            XElement result = new XElement(Constants.WORD_LIST_SUB_ELEMENT);
            result.SetAttributeValue("spell", wordCard.Spell);
            if (Helper.IsNotNullOrEmpty(wordCard.Meaning))
            {
                result.SetAttributeValue("meaning", wordCard.Meaning);
            }
            if (Helper.IsNotNullOrEmpty(wordCard.Synonym))
            {
                result.SetAttributeValue("synonym", wordCard.Synonym);
            }
            if (Helper.IsNotNullOrEmpty(wordCard.Antonym))
            {
                result.SetAttributeValue("antonym", wordCard.Antonym);
            }
            if (Helper.IsNotNullOrEmpty(wordCard.Remember))
            {
                result.SetAttributeValue("mnemonics", wordCard.Remember);
            }
            if (Helper.IsNotNullOrEmpty(wordCard.Leifan))
            {
                result.SetAttributeValue("leifan", wordCard.Leifan);
            }
            if (Helper.IsNotNullOrEmpty(wordCard.Derivation))
            {
                result.SetAttributeValue("derivation", wordCard.Derivation);
            }
            if (Helper.IsNotNullOrEmpty(wordCard.Place))
            {
                result.SetAttributeValue("place", wordCard.Place);
            }
            if (Helper.IsNotNullOrEmpty(wordCard.Webster))
            {
                result.SetAttributeValue("webster", wordCard.Webster);
            }
            return result;
        }
    }
}
